package com.xbongbong.paas.script.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.dao.PaasPrintTemplateDao;
import com.xbongbong.paas.domain.entity.PaasAppEntity;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasMenuEntity;
import com.xbongbong.paas.domain.entity.PaasPrintTemplateEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.help.menu.InitCrmMenuHelp;
import com.xbongbong.paas.model.PaasAppModel;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.model.PaasMenuModel;
import com.xbongbong.paas.pojo.dto.InitCompetitorMenuDTO;
import com.xbongbong.paas.service.PaasFormExplainService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CloneUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.wrap.XbbResponse;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.XbbProConstant;
import com.xbongbong.pro.enums.AccessLinkEnum;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.menu.enums.CRMMenuEnum;
import com.xbongbong.pro.script.pojo.dto.ScriptDTO;
import com.xbongbong.pro.script.pojo.vo.ScriptVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.script.service.InitExplainsService;
import com.xbongbong.saas.service.CompetitorService;
import com.xbongbong.sys.model.CompanyModel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author: yingjf
 * @date: 2022/8/11 11:01
 * @description: 竞争对手业务相关脚本
 */
@Slf4j
@RestController
@RequestMapping(XbbProConstant.API_ROOT_PREFIX+"/script/competitor")
public class CompetitorScriptController {
    @Resource
    private CompetitorService competitorService;
    @Resource
    private CompanyModel companyModel;
    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private PaasAppModel paasAppModel;
    @Resource
    private PaasMenuModel paasMenuModel;
    @Resource
    private InitCrmMenuHelp initCrmMenuHelp;
    @Resource
    private PaasFormExplainService paasFormExplainService;
    @Resource
    private InitExplainsService initExplainsService;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private PaasPrintTemplateDao paasPrintTemplateDao;

    @RequestMapping(value = "/initCompetitor", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String initCompetitor(@RequestBody @Valid ScriptDTO scriptDTO, BindingResult br) {
        XbbResponse<ScriptVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                ScriptVO scriptVO = initExplainsService.initCompetitor(scriptDTO);
                response = new XbbResponse<>(scriptVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }

    @RequestMapping(value = "/initCompetitorAnalysis", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String initCompetitorAnalysis(@RequestBody @Valid ScriptDTO scriptDTO, BindingResult br) {
        XbbResponse<ScriptVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                ScriptVO scriptVO = initExplainsService.initCompetitorAnalysis(scriptDTO);
                response = new XbbResponse<>(scriptVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }


    @RequestMapping(value = "/initMenuAndForm", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String init(@RequestBody @Valid InitCompetitorMenuDTO initCompetitorMenuDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(initCompetitorMenuDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        List<String> corpidList = initCompetitorMenuDTO.getCorpidList();
        if (corpidList == null || corpidList.isEmpty()) {
            corpidList = companyModel.getCorpidList();
        }
        Integer totalCount = corpidList.size();
        log.info("开始处理竞争对手菜单相关，数据库中共有" + totalCount + "家公司");
        int pageSize = 100;
        int totalPage = (totalCount % pageSize == 0) ? (totalCount / pageSize) : (totalCount / pageSize) + 1;
        int lastPageSize = (totalCount % pageSize == 0) ? pageSize : (totalCount % pageSize);
        long timeStart = DateTimeUtil.getInt();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //每个公司只有一个CRM
        param.put("alias", XbbRefTypeEnum.CRM.getAlias());
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        for (int page = 0; page < totalPage; page++) {
            List<String> subCorpidList = subCorpidList(corpidList, pageSize, totalPage, lastPageSize, page);
            List<PaasAppEntity> crmAppList = getPaasAppList(subCorpidList, param);
            Map<String, PaasAppEntity> corpCrmMenuMap = new HashMap<>(crmAppList.size());
            crmAppList.forEach(item->{
                corpCrmMenuMap.put(item.getCorpid(),item);
            });
            // 插入竞争对手菜单
            List<PaasMenuEntity> paasMenuEntityList = insertCompetitorMenu(crmAppList,corpCrmMenuMap,subCorpidList);
            Map<String,PaasMenuEntity> paasMenuEntityMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            paasMenuEntityList.forEach(item->{
                paasMenuEntityMap.put(item.getCorpid(),item);
            });
            // 插入竞争对手form表单
            List<PaasFormEntity> paasFormEntityList = insertCompetitorForm(paasMenuEntityList);
            Map<String,PaasFormEntity> paasFormEntityMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            paasFormEntityList.forEach(item->{
                paasFormEntityMap.put(item.getCorpid(),item);
            });

            insertDefaultExplain(corpidList,paasMenuEntityMap,paasFormEntityMap);
        }
        log.warn("竞争对手菜单相关处理完毕 time consume:" + (DateTimeUtil.getInt() - timeStart));
        return "处理完毕";
    }

    @RequestMapping(value = "/initPrintTemplate", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String initPrintTemplate(@RequestBody @Valid InitCompetitorMenuDTO initCompetitorMenuDTO, BindingResult br) throws Exception {

        if (!proBaseConfig.getXbbCode().equals(initCompetitorMenuDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        List<String> corpidList = initCompetitorMenuDTO.getCorpidList();
        if (corpidList == null || corpidList.isEmpty()) {
            corpidList = companyModel.getCorpidList();
        }
        Integer totalCount = corpidList.size();
        log.info("开始处理竞争对手默认相关，数据库中共有" + totalCount + "家公司");
        int pageSize = 100;
        int totalPage = (totalCount % pageSize == 0) ? (totalCount / pageSize) : (totalCount / pageSize) + 1;
        int lastPageSize = (totalCount % pageSize == 0) ? pageSize : (totalCount % pageSize);
        long timeStart = DateTimeUtil.getInt();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //每个公司只有一个CRM
        param.put("alias", XbbRefTypeEnum.CRM.getAlias());
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());

        PaasPrintTemplateEntity defaultCompetitorPrintTemplate = getDefaultCompetitorPrintTemplate();
        for (int page = 0; page < totalPage; page++) {
            List<String> subCorpidList = subCorpidList(corpidList, pageSize, totalPage, lastPageSize, page);
            Map<String, Object> paasFormParam = new HashMap<>();
            paasFormParam.put("corpidIn",subCorpidList);
            paasFormParam.put("businessType",XbbRefTypeEnum.COMPETITOR.getCode());
            // 根据公司id和业务类型查出该该公司下的竞争对手表单
            List<PaasFormEntityExt> paasFormEntityExtList = paasFormModel.findEntitys(paasFormParam);
            // 为这些公司刷上竞争对手默认打印模版
            if (CollectionUtils.isEmpty(paasFormEntityExtList)) {
                break;
            }

            insertCompetitorPrintTemplate(paasFormEntityExtList,defaultCompetitorPrintTemplate);

        }
        log.warn("竞争对手打印模版相关处理完毕 time consume:" + (DateTimeUtil.getInt() - timeStart));
        return "处理完毕";
    }

    @RequestMapping(value = "/removePrintTemplate", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String removePrintTemplate(@RequestBody @Valid InitCompetitorMenuDTO initCompetitorMenuDTO, BindingResult br) throws Exception{
        try {
            if (!proBaseConfig.getXbbCode().equals(initCompetitorMenuDTO.getXbbCode())) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
            }
            List<String> corpidList = initCompetitorMenuDTO.getCorpidList();
            if (corpidList == null || corpidList.isEmpty()) {
                corpidList = companyModel.getCorpidList();
            }
            Integer totalCount = corpidList.size();
            log.info("开始回滚竞争对手默认打印模版，数据库中共有" + totalCount + "家公司");
            int pageSize = 100;
            int totalPage = (totalCount % pageSize == 0) ? (totalCount / pageSize) : (totalCount / pageSize) + 1;
            int lastPageSize = (totalCount % pageSize == 0) ? pageSize : (totalCount % pageSize);
            long timeStart = DateTimeUtil.getInt();
            for (int page = 0; page < totalPage; page++) {
                List<String> subCorpidList = subCorpidList(corpidList, pageSize, totalPage, lastPageSize, page);
                Map<String, Object> getParamMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                getParamMap.put("corpidIn",subCorpidList);
                getParamMap.put("businessType",XbbRefTypeEnum.COMPETITOR.getCode());
                getParamMap.put("del",DelEnum.NORMAL.getDel());
                List<PaasPrintTemplateEntity> templateList = paasPrintTemplateDao.findEntitys(getParamMap);
                if (CollectionUtils.isEmpty(templateList)){
                    break;
                }
                List<Long> removeIdList = templateList.stream().map(item -> item.getId()).collect(Collectors.toList());
                Map<String, Object> removeParamMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                removeParamMap.put("idIn",removeIdList);
                removeParamMap.put("businessType",XbbRefTypeEnum.COMPETITOR.getCode());
                removeParamMap.put("del",DelEnum.NORMAL.getDel());
                paasPrintTemplateDao.deleteBatch4RollBack(removeParamMap);
            }
            log.info("回滚竞争对手默认打印模版结束：耗时：" + (DateTimeUtil.getInt() - timeStart));
        }catch (Exception e){
            log.error("竞争对手回滚默认打印模版异常 exception："+ e);
        }
        return "处理完毕";
    }


    void insertDefaultExplain(List<String> corpidList,Map<String,PaasMenuEntity> paasMenuEntityMap,Map<String,PaasFormEntity> paasFormEntityMap)throws XbbException{
        long now = DateTimeUtil.getInt();
        List<PaasFormExplainEntity> insert = new ArrayList<>();
        corpidList.forEach(corpid->{
            PaasMenuEntity paasMenuEntity = paasMenuEntityMap.get(corpid);
            if(paasMenuEntity==null){
                return;
            }
            Long menuId = paasMenuEntity.getId();
            Long appId = paasMenuEntity.getAppId();
            PaasFormEntity paasFormEntity = paasFormEntityMap.get(corpid);
            if(paasFormEntity==null){
                return;
            }
            Long formId = paasFormEntity.getId();
            PaasFormExplainEntity paasFormExplainEntity = new PaasFormExplainEntity(corpid, appId, menuId, formId, 1,
                    JSON.toJSONString(new JSONArray()), "1", now, now, DelEnum.NORMAL.getDel(), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.COMPETITOR.getCode(), DistributorMarkEnum.OTHER.getCode());
            insert.add(paasFormExplainEntity);
        });
        if(CollectionUtils.isNotEmpty(insert)){
            paasFormExplainModel.insertBatch(insert);
        }
    }

    List<PaasFormEntity> insertCompetitorForm(List<PaasMenuEntity> paasMenuEntityList) throws XbbException{
        List<PaasFormEntity> paasFormEntities = new ArrayList<>();
        String summary = JSON.toJSONString(initCrmMenuHelp.getAppDefaultSummary(XbbRefTypeEnum.COMPETITOR.getCode()));
        String customTitle = JSON.toJSONString(initCrmMenuHelp.getAppDefaultTitle(XbbRefTypeEnum.COMPETITOR.getCode()));
        long now = DateUtil.getNow();
        List<PaasFormEntity> formEntityList = new ArrayList<>();
        paasMenuEntityList.forEach(item->{
            String corpid = item.getCorpid();
            Long appId = item.getAppId();
            Long menuId = item.getId();
            Integer saasMark = SaasMarkEnum.SAAS.getCode();
            Integer businessType = XbbRefTypeEnum.COMPETITOR.getCode();
            Integer enable = BasicConstant.ONE;
            String name = XbbRefTypeEnum.COMPETITOR.getName();

            PaasFormEntity formEntity = new PaasFormEntity(corpid, appId, menuId,name , saasMark,
                    businessType, enable, 0, "", 1, 0, 2,
                    customTitle, "", "", "", null, null, summary, "",
                    "", "", "1", now, now, DelEnum.NORMAL.getDel(), null, 0, DistributorMarkEnum.OTHER.getCode());
            formEntityList.add(formEntity);
        });
        try {
            if (formEntityList.size() > 0) {
                paasFormEntities = paasFormModel.insertBatch(formEntityList);
                log.warn("tb_paas_form：" + formEntityList.size() + "条竞争对手表单插入成功");
            }
        } catch (Exception e) {
            log.error("FundMenuScriptController.handleForm4Sheet form数据库批量设置出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return paasFormEntities;
    }

    List<PaasMenuEntity> insertCompetitorMenu(List<PaasAppEntity> crmAppList,Map<String, PaasAppEntity> corpCrmMenuMap,List<String> corpidList) throws XbbException{
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpidIn", corpidList);
        param.put("alias", XbbRefTypeEnum.COMPETITOR.getAlias());
        param.put("del", DelEnum.NORMAL.getDel());
        List<PaasMenuEntity> exitPaasMenuEntityList = paasMenuModel.findEntitys(param);
        Set<String> exitCorpidSet = new HashSet<>();
        exitPaasMenuEntityList.forEach(item->{
            exitCorpidSet.add(item.getCorpid());
        });
        List<PaasMenuEntity> insertList = new ArrayList<>();
        AccessLinkEnum accessLinkEnum = AccessLinkEnum.COMPETITOR;
        CRMMenuEnum crmMenuEnum = CRMMenuEnum.COMPETITOR;
        String alias = crmMenuEnum.getAlias();
        String name = crmMenuEnum.getName();
        for (PaasAppEntity entity : crmAppList) {
            Long appId = entity.getId();
            String corpid = entity.getCorpid();
            if(exitCorpidSet.contains(corpid)){
                // 有的就不加了
                continue;
            }
            PaasMenuEntity paasMenuEntity = new PaasMenuEntity(corpid, appId, name, alias, 99, accessLinkEnum.getUrl(), accessLinkEnum.getMobileUrl(), BasicConstant.ONE, accessLinkEnum.getColor(), accessLinkEnum.getIcon(), "1");
            insertList.add(paasMenuEntity);
        }
        try {
            if (insertList.size() > 0) {
                paasMenuModel.insertBatch(insertList);
                log.warn(insertList.size() + "条竞争对手菜单插入成功");
            }
        } catch (Exception e) {
            log.error("CompetitorScriptController.insertCompetitorMenu menu数据库批量设置竞争对手菜单出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return insertList;
    }

    /**
     * 为指定公司新增竞争对手默认打印模版
     * @param paasFormEntityExtList
     * @param defaultTemplate
     * @throws Exception
     */
    void insertCompetitorPrintTemplate(List<PaasFormEntityExt> paasFormEntityExtList,PaasPrintTemplateEntity defaultTemplate) throws Exception{

        List<PaasPrintTemplateEntity> templateEntityList = new ArrayList<>();

        for (PaasFormEntityExt paasForm : paasFormEntityExtList) {
            String corpid = paasForm.getCorpid();
            Long formId = paasForm.getId();
            Long appId = paasForm.getAppId();
            Long menuId = paasForm.getMenuId();
            Integer businessType = paasForm.getBusinessType();
            // 先检查该公司下是否已经存在竞争对手打印模版
            HashMap<String, Object> param = new HashMap<>();
            param.put("corpid",corpid);
            param.put("formId",formId);
            param.put("del",0);
            param.put("businessType",businessType);
            param.put("distributorMark", 0);
            Integer existTemplateCount = paasPrintTemplateDao.getEntitysCount(param);
            if (existTemplateCount!= null && existTemplateCount > 0){
                continue;
            }

            // 为该公司新增竞争对手默认模版
            PaasPrintTemplateEntity template = (PaasPrintTemplateEntity) CloneUtil.deepClone(defaultTemplate);
            template.setCorpid(corpid);
            template.setAppId(appId);
            template.setMenuId(menuId);
            template.setFormId(formId);

            templateEntityList.add(template);
        }

        try {
            if (CollectionUtils.isNotEmpty(templateEntityList)) {
                paasPrintTemplateDao.insertBatch(templateEntityList);
            }
        }catch (Exception e){
            log.error("CompetitorScriptController.insertCompetitorPrintTemplate 竞争对手默认打印模版新增出错，出错原因: ", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }

    }

    private PaasPrintTemplateEntity getDefaultCompetitorPrintTemplate(){
        PaasPrintTemplateEntity defaultPrintTemplate = null;
        try {
            Map<String, Object> param = new HashMap<>();
            param.put("corpid","0");
            param.put("formId","0");
            param.put("appId","0");
            param.put("businessType",XbbRefTypeEnum.COMPETITOR.getCode());
            List<PaasPrintTemplateEntity> templateList = paasPrintTemplateDao.findEntitys(param);
            defaultPrintTemplate= Optional.of(templateList.get(0)).orElseThrow(() -> new Exception("竞争对手默认打印模版不存在"));
        }catch (Exception e){
            log.error("CompetitorScriptController.getDefaultCompetitorPrintTemplate 竞争对手获取默认打印模版出错，出错原因: ", e);
        }
        return defaultPrintTemplate;
    }

    /**
     * 得到当前页的公司id列表
     * @param corpidList 所有的公司id列表
     * @param pageSize 每页个数
     * @param totalPage 总页数
     * @param lastPageSize 最后一页的个数
     * @param page 页码
     * @return java.util.List<java.lang.String>
     */
    private List<String> subCorpidList(List<String> corpidList, int pageSize, int totalPage, int lastPageSize, int page) {
        int fromIndex = page * pageSize;
        int toIndex = fromIndex + pageSize;
        if (page == totalPage - 1) {
            toIndex = fromIndex + lastPageSize;
        }
        return corpidList.subList(fromIndex, toIndex);
    }

    private List<PaasAppEntity> getPaasAppList(List<String> subCorpidList, Map<String, Object> param) {
        param.put("corpidIn", subCorpidList);
        param.put("saasMark", SaasMarkEnum.SAAS.getCode());
        return paasAppModel.findEntitys(param);
    }
}
